<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    // 重写数组原型：
    let ArrayPrototy = Array.prototype;
    // 当前原型会指向ArrayPrototy， 他不会影响原型上的方法；
    let arrProto = Object.create(ArrayPrototy);

    // this.arr.push(a)

    ['push', 'pop', 'slice', 'splice'].forEach(methodName => {
      arrProto[methodName] = function () {
        ArrayPrototy.call(this, ...arguments)
        updateView()
      }
    })
    function updateView() {
      console.log('视图更新了！')
    }
    // data : {}
    function definReactive(target, key, value) {
      observer(value)
      Object.defineProperty(target, key, {
        get() {
          return value
        },
        set(newVal) {
          // console.log(newVal, 'newVal')
          if (newVal !== value) {
            observer(newVal) // 更改对象视图
            value = newVal; // value一直在闭包环境中，再get也能获取到新的值
            updateView()
          }
        }
      })
    }

    // viewModle
    function observer(target) {
      if (typeof target !== 'object' || target === null) {
        // 不是对象或者数组
        return target;
      }
      // 关于数组的判断
      if (Array.isArray(target)) {
        target.__proto__ = arrProto;
      }
      // console.log(target)
      for (let key in target) {
        definReactive(target, key, target[key])
      }
    }

    const data = {
      name: 'zhangsan',
      age: '22222',
      info: { address: '88' },
      arr: []
    }

    observer(data);

    // data.x = '122'; // 新增属性，vue监听不到，所有有Vue.set
    // data.name = 'name';
    // data.age = { name: 1 }
    // data.age.name = 12
    data.arr.push(1)
    // 数组：push slice splice 重写



    // data.name = 'name';
    // data.age = 12;
    // data.age = { name: 12 };
    // data.age.name = 1212;
    // data.age.name = 13;

    delete data.name // 删除属性，监听不到，所有有了Vue.delete

    // data.info.address = '长三角' // 深度监听
    data.arr.push(23) // 监听数组

    /**
     *  1. 新增属性
     *  2. 删除属性
     *  3. 深度监听
     *  4. 监听数组
     */

    // 如何深度监听

    // 如何监听数组变化

    /**
     react Hooks

     setState的更新机制



    */

  </script>
</body>

</html>
